﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SCG.General
{
    public class SCGPoint
    {
        public SCGPoint()
        {
        }
        public SCGPoint(int x, int y)
        {
            X = x;
            Y = y;
        }
        public SCGPoint(SCGPoint pt)
        {
            X = pt.X;
            Y = pt.Y;
        }

        public int X { get; set; }
        public int Y { get; set; }

        public override string ToString()
        {
            return X + "," + Y;
        }

        public void Offset(int offsetX, int offsetY)
        {
            X += offsetX;
            Y += offsetY;
        }
        public void Offset(SCGPoint pt)
        {
            Offset(pt.X, pt.Y);
        }

        public bool EqualsPoint(SCGPoint pt)
        {
            return X == pt.X && Y == pt.Y;
        }

        public int DistanceQuick(SCGPoint pt)
        {
            return Math.Abs(X - pt.X) + Math.Abs(Y - pt.Y);
        }
        public int DistanceQuick(int x, int y)
        {
            return Math.Abs(X - x) + Math.Abs(Y - y);
        }

        public SCGDirection DirectionToward(int x, int y)
        {
            int diffX = x - X;
            int diffY = y - Y;
            if (Math.Abs(diffX) > Math.Abs(diffY))
            {
                return diffX > 0 ? SCGDirection.Right : SCGDirection.Left;
            }
            else
            {
                return diffY > 0 ? SCGDirection.Down : SCGDirection.Up;
            }
        }
        public SCGDirection DirectionToward(SCGPoint pt)
        {
            return DirectionToward(pt.X, pt.Y);
        }

        public SCGDirection8 DirectionToward8(int x, int y)
        {
            int xdiff = x - X;
            int ydiff = y - Y;
            if (xdiff == 0 && ydiff == 0)
                return SCGDirection8.Up;

            //if adjacent use simple calc
            if (Math.Abs(xdiff) <= 1 && Math.Abs(ydiff) <= 1)
            {
                if (xdiff == 1)
                {
                    if (ydiff == 0)
                        return SCGDirection8.Right;
                    else if (ydiff == 1)
                        return SCGDirection8.DownRight;
                    else
                        return SCGDirection8.UpRight;
                }
                else if (xdiff == -1)
                {
                    if (ydiff == 0)
                        return SCGDirection8.Left;
                    else if (ydiff == 1)
                        return SCGDirection8.DownLeft;
                    else
                        return SCGDirection8.UpLeft;
                }
                else
                {
                    if (ydiff == 1)
                        return SCGDirection8.Down;
                    else
                        return SCGDirection8.Up;
                }
            }

            SCGDirection8 dir;
            if (xdiff == 0)
                return ydiff > 0 ? SCGDirection8.Down : SCGDirection8.Up;
            if (ydiff == 0)
                return xdiff > 0 ? SCGDirection8.Right : SCGDirection8.Left;
            if (xdiff > 0)
                dir = ydiff == 0 ? SCGDirection8.Right : ydiff > 0 ? SCGDirection8.DownRight : SCGDirection8.UpRight                                                       ;
            else
                dir = ydiff == 0 ? SCGDirection8.Left : ydiff > 0 ? SCGDirection8.DownLeft : SCGDirection8.UpLeft;
            return dir;
        }
        public SCGDirection8 DirectionToward8(SCGPoint pt)
        {
            return DirectionToward8(pt.X, pt.Y);
        }
    }

    public static class PointExtensions
    {
        public static bool ContainsPoint(this List<SCGPoint> lst, SCGPoint pt)
        {
            foreach(SCGPoint pt2 in lst)
                if (pt2.EqualsPoint(pt))
                    return true;
            return false;
        }

        public static void RemovePoint(this List<SCGPoint> lst, SCGPoint pt)
        {
            for (int n = lst.Count - 1; n >= 0; n--)
            {
                SCGPoint testPt = lst[n];
                if (testPt.EqualsPoint(pt))
                    lst.Remove(testPt);
            }
        }
    }
}
